<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    function scientificNotationToString(val) {
        val = String(val)
        if (val.indexOf('-') >= 0) {
            val = '0' + String(Number(val) + 1).substring(1);
        }
        return val
    }

    class NumberTool {
        static format(data, rules) {
            // eslint-disable-next-line no-self-compare
            const condition = (typeof data === 'number' && (data === data)) || typeof data === 'string';
            if (Object.prototype.toString.call(data) === '[object Object]') {
                return NumberTool.objectFormat(data, rules);
            } else if (Array.isArray(data)) {
                data.forEach(item => {
                    NumberTool.objectFormat(item, rules);
                });
                return data; // 返回
            } else if (condition) {
                const {
                    precision,
                    roundingMode
                } = rules[0];
                return NumberTool.simpleDataFormat(data, precision, roundingMode); // 返回 number
            }
            return data;
        }

        /**
         * 对象的格式化，针对数据做处理，不补零
         * @param data
         * @param rules
         */
        static objectFormat(data, rules) {
            const keys = Object.keys(data);
            const ruleFields = rules.map(item => item.field);
            keys.forEach(key => {
                if (ruleFields.indexOf(key) > -1) {
                    const index = rules.findIndex(rule => rule.field === key);
                    const {
                        precision,
                        roundingMode
                    } = rules[index];
                    data[key] = NumberTool.simpleDataFormat(data[key], precision, roundingMode);
                }
            });
            return data;
        }

        /**
         * 基础数据类型的格式化
         * @param data 需要转换的数据
         * @param precision 精度
         * @param roundingMode 取整方式
         */
        static simpleDataFormat(data, precision, roundingMode) {
            let result = NumberTool.getNumber(data);
            if (roundingMode === 'rounding') {
                result = NumberTool.round(result, precision);
            }
            return result;
        }

        /**
         * 根据精度进行补 0，比如：1.8 保留两位是 '1.80'
         * 返回字符串，仅作页面展示
         * @param number
         * @param precision
         */
        static numberToString(number, precision) {
            try {
                number = isNaN(Number(number)) ? 0 : Number(number);
                number = NumberTool.round(number, precision).toString();
                const arr = number.split('.');
                const integer = arr[0];
                const decimal = arr[1] || '';

                return decimal.length === precision ? number : `${integer}.${decimal}${'0'.repeat(precision - decimal.length)}`;
            } catch (e) {
                throw new Error(`${e} 传入的数据有误，不是数值！！！`);
            }
        }

        /**
         * 取整方法
         * @param number
         * @param precision
         * @private
         */
        static round(number, precision) {
            // 考虑 JavaScript 自动转换科学计数法
            const condition = number.toString().includes('e')
            if (condition) {
                const result = scientificNotationToString(number)
                const arr = result.split('.');
                const integer = arr[0];
                const decimal = arr[1] || '';
                // result:0.0000006 integer:0 decimal:0000006 precision:6
                if (decimal.length > precision) {
                    // 根据精度，截取到指定的小数位片段 000000
                    let frontSection = decimal.substring(0, precision)
                    // 根据精度，截取到小数位的后一位，作为进1判断
                    const latterNum = decimal[precision]
                    if (latterNum >= 5) {
                        // 最后一位需要进1，取到最后一位+1，再与前面的片段拼接
                        frontSection = frontSection.substring(0, frontSection.length - 1) + (Number(frontSection.substring(frontSection.length - 1)) + 1)
                    }
                    // console.log(`latterNum:${latterNum} frontSection:${frontSection}`)
                    return Number(`${integer}.${frontSection}`)
                }

                // console.log(
                //     `result:${result} integer:${integer} decimal:${decimal} precision:${precision}`
                // )
                return result
            }
            return Math.round(Number(+number + 'e' + precision)) / Math.pow(10, precision);
        }

        /**
         * 返回一个有效的数值，不可转为有效数值的转为 0
         * @param number
         * @private
         */
        static getNumber(number) {
            try {
                return Number(number);
            } catch (e) {
                console.warn(`${e} 传入的数据有误，不是数值！！！`);
                return 0;
            }
        }
    }

    // 6位小数
    console.log(NumberTool.numberToString(0.000006, 8)); // 0.00000600 正常
    console.log(NumberTool.numberToString(0.000006, 6)); // 0.000006 正常
    console.log(NumberTool.numberToString(0.000006, 4)); // 0.0000 正常
    // 6为以上小数
    console.log(NumberTool.numberToString(0.0000006, 3)) // 0.000
    console.log(NumberTool.numberToString(0.0000006, 6)) // 0.000001
    console.log(NumberTool.numberToString(0.0000006, 7)) // 0.0000006
    console.log(NumberTool.numberToString(0.0000006, 8)) // 0.00000060
    console.log(NumberTool.numberToString(0.0000001, 7))    // 0.0000001
    console.log(NumberTool.numberToString(0.0000001, 8))    // 0.00000010

    console.log(NumberTool.numberToString(1.2, 8))    // 0.00000010
    console.log(NumberTool.numberToString(1.25, 1))    // 0.00000010
    console.log(NumberTool.numberToString(1.2393335, 8))    // 0.00000010
</script>
</body>
</html>
